package pl.shenlon.poker.gui.testhands;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;

import net.miginfocom.swing.MigLayout;
import pl.shenlon.poker.cards.Hand;
import pl.shenlon.poker.cards.deck.Deck;
import pl.shenlon.poker.cards.deck.PokerDeck;
import pl.shenlon.poker.cards.evaluation.HandRankEvaluator;
import pl.shenlon.poker.game.TestHand;

public class TestHandsCreationDialog extends JDialog {
	private String[] availableCards;

	private List<JComboBox<String>> comboBoxes;

	private TestHand createdHand;

	private Deck deck;

	private final HandRankEvaluator evaluator;

	private ItemListener itemListener;

	private ComboBoxModel<String>[] playerAHandComboBoxModels,
			playerBHandComboBoxModels, tableHandComboBoxModels;

	private JLabel playerAHandLabel, playerBHandLabel, tableHandLabel,
			playerAHandStrengthLabel, playerBHandStrengthLabel;

	private final boolean setUp;

	private JButton submitButton, cancelButton;

	public TestHandsCreationDialog() {
		initComponent();
		setDeck(new PokerDeck());
		setUp = true;
		evaluator = HandRankEvaluator.getInstance();
		setTitle("Dodaj rękę testową");
		setModal(true);
		pack();
		setResizable(false);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
	}

	public String[] getAvailableCards() {
		return availableCards;
	}
	public TestHand getCreatedHand() {
		return createdHand;
	}

	public Deck getDeck() {
		return deck;
	}

	@SuppressWarnings("unchecked")
	private void initComponent() {
		Container contentPane = getContentPane();
		contentPane.setLayout(new MigLayout());

		comboBoxes = new ArrayList<JComboBox<String>>();
		itemListener = new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent event) {
				if (!setUp) {
					return;
				}
				if (event.getStateChange() == ItemEvent.SELECTED) {
					boolean correctData = true;
					List<String> selectedItems = new ArrayList<String>();
					for (JComboBox<String> comboBox : comboBoxes) {
						String item = (String) comboBox.getSelectedItem();
						if (selectedItems.contains(item)) {
							correctData = false;
							break;
						}
						selectedItems.add(item);
					}

					if (correctData) {
						submitButton.setEnabled(true);
						prepareTestHand();
					} else {
						submitButton.setEnabled(false);
					}

				}
			}
		};

		playerAHandComboBoxModels = new ComboBoxModel[]{
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),};

		playerBHandComboBoxModels = new ComboBoxModel[]{
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),};

		tableHandComboBoxModels = new ComboBoxModel[]{
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),
				new DefaultComboBoxModel<String>(),};

		playerAHandLabel = new JLabel("Ręka pierwszego gracza");
		playerBHandLabel = new JLabel("Ręka drugiego gracza");
		tableHandLabel = new JLabel("Karty na stole");
		playerAHandStrengthLabel = new JLabel("");
		playerBHandStrengthLabel = new JLabel("");

		contentPane.add(playerAHandLabel, "split 2, span");
		contentPane.add(playerAHandStrengthLabel, "wrap");
		populateComboBoxes(playerAHandComboBoxModels, contentPane);

		contentPane.add(tableHandLabel, "span, wrap");
		populateComboBoxes(tableHandComboBoxModels, contentPane);

		contentPane.add(playerBHandLabel, "split 2, span");
		contentPane.add(playerBHandStrengthLabel, "wrap");
		populateComboBoxes(playerBHandComboBoxModels, contentPane);

		submitButton = new JButton("Dodaj rękę");
		submitButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent event) {
				if (createdHand == null) {
					prepareTestHand();
				}
				setVisible(false);
			}
		});

		cancelButton = new JButton("Anuluj");
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				createdHand = null;
				setVisible(false);
			}
		});

		contentPane.add(submitButton, "split 2, w 50%, span");
		contentPane.add(cancelButton, "w 50%, wrap");
		getRootPane().setDefaultButton(cancelButton);
	}

	private void populateComboBoxes(ComboBoxModel<String>[] array,
			Container contentPane) {
		for (int i = 0; i < array.length; i++) {
			JComboBox<String> comboBox = new JComboBox<String>(array[i]);
			comboBox.addItemListener(itemListener);
			if (i == array.length - 1) {
				contentPane.add(comboBox, "wrap");
			} else {
				contentPane.add(comboBox);
			}
			comboBoxes.add(comboBox);
		}
	}

	private void prepareTestHand() {
		StringBuilder line = new StringBuilder();
		for (ComboBoxModel<String> model : playerAHandComboBoxModels) {
			line.append(model.getSelectedItem()).append("-");
		}
		line.replace(line.length() - 1, line.length(), " ");

		for (ComboBoxModel<String> model : playerBHandComboBoxModels) {
			line.append(model.getSelectedItem()).append("-");
		}
		line.replace(line.length() - 1, line.length(), " ");

		for (ComboBoxModel<String> model : tableHandComboBoxModels) {
			line.append(model.getSelectedItem()).append("-");
		}
		line.replace(line.length() - 1, line.length(), "");
		createdHand = new TestHand(line.toString());
		Hand tableCards = createdHand.getTableCards();
		tableCards.show();
		playerAHandStrengthLabel.setText("("
				+ evaluator.evaluateHand(createdHand.getPlayerACards(),
						tableCards) + ")");
		playerBHandStrengthLabel.setText("("
				+ evaluator.evaluateHand(createdHand.getPlayerBCards(),
						tableCards) + ")");
	}

	public void setDeck(Deck deck) {
		this.deck = deck;
		availableCards = new String[deck.length];
		for (int i = 0; i < deck.length; i++) {
			availableCards[i] = deck.getCardAtPosition(i).toString();
		}
		int i = 0;
		for (JComboBox<String> comboBox : comboBoxes) {
			int comboBoxSize = comboBox.getModel().getSize();

			for (int j = 0; j < comboBoxSize; j++) {
				comboBox.removeItemAt(0);
			}
			for (String card : availableCards) {
				comboBox.addItem(card);
			}
			comboBox.setSelectedIndex(i);
			i++;
		}
	}
}